package com.fire.control.system.module.excel.service.impl;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fire.control.system.dto.MaintenceListDTO;
import com.fire.control.system.dto.UnsolvedListDTO;
import com.fire.control.system.module.excel.controller.ExcelController;
import com.fire.control.system.module.excel.service.ExcelService;
import com.fire.control.system.module.warning.dao.WarningInfoMapper;
import com.fire.control.system.module.warning.dao.WarningMapper;
import com.fire.control.system.statics.Status_Warning;
import com.fire.control.system.support.protocol.device.DeviceRequestProtocol;
import com.fire.control.system.support.util.ExcelUtil;

import net.sf.json.JSONArray;


/**
 * 
 * @ClassName:  ExcelServiceImpl
 * @Description:  导入导出excel接口具体实现
 * @author:  xiechengguang
 * @date:  2017年6月24日 下午6:33:54
 *
 */
@Service
public class ExcelServiceImpl implements ExcelService {
	private static final Logger log = LoggerFactory.getLogger(ExcelController.class);
	
	@Autowired private WarningMapper warningMapper;
	@Autowired private WarningInfoMapper warningInfoMapper;
	private SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
	private SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	/**
	 * <p>Author: xiechengguang</p> 
	 * <p>Title: export</p> 
	 * <p>Description: 导出excel</p> 
	 * @param request
	 * @param response 
	 * @see com.fire.control.system.module.excel.service.ExcelService#export(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	 */
	@Override
	public void export(HttpServletRequest request, HttpServletResponse response, DeviceRequestProtocol reqProtocol) {
		int tag = reqProtocol.getTag();
		
    	
    	JSONArray jsonArray = new JSONArray();
    	Map<String,String> headMap = new LinkedHashMap<>();
        OutputStream outXls = null;
        String title = null;
        
 		try {
 			if(tag==1) {
 				List<MaintenceListDTO> list = new ArrayList<MaintenceListDTO>();
 				list = warningMapper.searchDeviceMaintences(reqProtocol);
 				for (MaintenceListDTO dto : list) {
 					dto.setCurrentStatus(Status_Warning.getValue(dto.getCurrentStatus()));
				}
 		    	jsonArray = this.setMatainceDate(list);
 		    	headMap = this.setMaintenceHeads();
 	    		title = "维保设备数据";
// 	    		outXls = new FileOutputStream("E:\\excel/维保设备"+sdf.format(new Date())+".xls");
 	    		log.info("共"+list.size()+"数据========");
 	    	} else if(tag==2) {
 	    		List<UnsolvedListDTO> list = new ArrayList<UnsolvedListDTO>();
 	    		list = warningInfoMapper.searchSolvedWarnings(reqProtocol);
 	    		for (UnsolvedListDTO unsolvedListDTO : list) {
 	    			unsolvedListDTO.setCurrentStatus(Status_Warning.getValue(unsolvedListDTO.getCurrentStatus()));
				}
 		    	jsonArray = this.setWarningDate(list);
 		    	headMap = this.setWarningHeads();
 	    		title = "报警列表数据";
 	    		outXls = new FileOutputStream("E:\\excel/报警列表"+sdf.format(new Date())+".xls");
 	    		log.info("共"+list.size()+"数据========");
 	    	}
 	        log.info("正在导出xls....");
 	        Date d = new Date();
// 	        ExcelUtil.downloadExcelFile(title,headMap,jsonArray,response); //在浏览器显示下载方式
 	        ExcelUtil.exportExcel(title,headMap,jsonArray,null,0,outXls); //不显示下载方式
 	        log.info("共用时"+(new Date().getTime()-d.getTime())+"ms");
 	         
 			
 	        /*OutputStream outXlsx = new FileOutputStream("E:\\excel/test.xlsx");
	        System.out.println("正在导出xlsx....");
	        Date d2 = new Date();
	        ExcelUtil.exportExcelX(title,headMap,ja,null,0,outXlsx);
	        System.out.println("共"+count+"条数据,执行"+(new Date().getTime()-d2.getTime())+"ms");*/
 		} catch (FileNotFoundException e) {
 			e.printStackTrace();
 		} finally {
 			try {
 				if(outXls != null) {
 					outXls.close();
 				}
 			} catch (IOException e) {
 				e.printStackTrace();
 			}
 		}
    	
	}
	
	

	/**
	 * @author: xiechengguang 
	 * @Title: setMatainceDate   
	 * @Description: 数据存入JsonArray  
	 * @param:        
	 * @return: JSONArray      
	 * @throws
	 */
	public JSONArray setMatainceDate(List<MaintenceListDTO> mList) {
		JSONArray jsonArray = new JSONArray();
        for(MaintenceListDTO dto : mList){
        	dto.setShowTime(sdf2.format(dto.getStartTime()));
            jsonArray.add(dto);
        }
        return jsonArray;
	}
	
	/**
	 * @author: xiechengguang 
	 * @Title: setWarningDate   
	 * @Description: 数据存入JsonArray  
	 * @param:        
	 * @return: JSONArray      
	 * @throws
	 */
	public JSONArray setWarningDate(List<UnsolvedListDTO> mList) {
		JSONArray jsonArray = new JSONArray();
        for(UnsolvedListDTO dto : mList){
        	dto.setShowTime(sdf2.format(dto.getStartTime()));
        	dto.setLastTime(sdf2.format(dto.getEndTime()));
            jsonArray.add(dto);
        }
        return jsonArray;
	}
	
	/**
	 * @author: xiechengguang 
	 * @Title: setMaintenceHeads   
	 * @Description: 设置导出表格头  
	 * @param:        
	 * @return: Map<String,String>      
	 * @throws
	 */
	public Map<String,String> setMaintenceHeads() {
		 Map<String,String> headMap = new LinkedHashMap<String,String>();
	        headMap.put("deviceName","设备名称");
	        headMap.put("serialNumber","设备编号");
//	        headMap.put("gatewayNum", "网关编号");
	        headMap.put("groupName","设备组");
	        headMap.put("onlineStatus","在线状态");
	        headMap.put("warningDesc","维保描述");
	        headMap.put("showTime","报警时间");
	        headMap.put("solutionDesc","处理说明");
	        headMap.put("mergerName","所在位置");
	        headMap.put("manager","负责人");
	        headMap.put("companyName","所属企业");
	        headMap.put("currentStatus","处理状态");
	        
	    return headMap;
	}
	
	/**
	 * @author: xiechengguang 
	 * @Title: setWarningHeads   
	 * @Description: 设置导出表格头  
	 * @param:        
	 * @return: Map<String,String>      
	 * @throws
	 */
	public Map<String,String> setWarningHeads() {
		 Map<String,String> headMap = new LinkedHashMap<String,String>();
		 	headMap.put("warningDesc","报警描述");
	        headMap.put("deviceName","报警设备名称");
	        headMap.put("serialNumber","报警设备编号");
	        headMap.put("deviceType","设备类型");
	        headMap.put("address","报警位置");
	        headMap.put("showTime","报警时间");
	        headMap.put("lastTime","报警时间");
	        headMap.put("currentStatus","处理状态");
	        headMap.put("manager","负责人");
	        headMap.put("companyName","所属企业");
	        headMap.put("warningType","报警类型");
	        
	    return headMap;
	}
	
	
	
	/** 
     * @Title: createWorkbook 
     * @Description: 判断excel文件后缀名，生成不同的workbook 
     * @param @param is
     * @param @param excelFileName
     * @param @return
     * @param @throws IOException
     * @return Workbook
     * @throws 
     */
     public Workbook createWorkbook(InputStream is,String excelFileName) throws IOException{
         if (excelFileName.endsWith(".xls")) {
             return new HSSFWorkbook(is);
         }else if (excelFileName.endsWith(".xlsx")) {
             return new XSSFWorkbook(is);
         }
         return null;
     }

    /** 
     * @Title: getSheet 
     * @Description: 根据sheet索引号获取对应的sheet
     * @param @param workbook
     * @param @param sheetIndex
     * @param @return
     * @return Sheet
     * @throws 
     */
     public Sheet getSheet(Workbook workbook,int sheetIndex){
         return workbook.getSheetAt(0);        
     }
     
    /** 
     * 
     * @Title: importDataFromExcel 
     * @Description: 将sheet中的数据保存到list中，
     * 1、调用此方法时，vo的属性个数必须和excel文件每行数据的列数相同且一一对应，vo的所有属性都为String
     * 2、在action调用此方法时，需声明 
     *     private File excelFile;上传的文件
     *     private String excelFileName;原始文件的文件名
     * 3、页面的file控件name需对应File的文件名
     * @param @param vo javaBean
     * @param @param is 输入流
     * @param @param excelFileName
     * @param @return
     * @return List<Object>
     * @throws 
     */
     @Override
     public List<Object> importDataFromExcel(Object vo,InputStream is,String excelFileName){
         List<Object> list = new ArrayList<Object>();
         try {
             //创建工作簿
             Workbook workbook = this.createWorkbook(is, excelFileName);
             //创建工作表sheet
             Sheet sheet = this.getSheet(workbook, 0);
             //获取sheet中数据的行数
             int rows = sheet.getPhysicalNumberOfRows();
             //获取表头单元格个数
             int cells = sheet.getRow(0).getPhysicalNumberOfCells();
             //利用反射，给JavaBean的属性进行赋值
             Field[] fields = vo.getClass().getDeclaredFields();
             for (int i = 1; i < rows; i++) {//第一行为标题栏，从第二行开始取数据
                 Row row = sheet.getRow(i);
                 int index = 0;
                 while (index < cells) {
                     Cell cell = row.getCell(index);
                     if (null == cell) {
                         cell = row.createCell(index);
                     }
                     cell.setCellType(Cell.CELL_TYPE_STRING);
                     String value = null == cell.getStringCellValue()?"":cell.getStringCellValue();
                     
                     Field field = fields[index];
                     String fieldName = field.getName();
                     String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
                     Method setMethod = vo.getClass().getMethod(methodName, new Class[]{String.class});
                     setMethod.invoke(vo, new Object[]{value});
                     index++;
                 }
                 if (isHasValues(vo)) {//判断对象属性是否有值
                     list.add(vo);
                     vo.getClass().getConstructor(new Class[]{}).newInstance(new Object[]{});//重新创建一个vo对象
                 }
                 
             }
         } catch (Exception e) {
             log.error(e.getMessage());
         }finally{
             try {
                 is.close();//关闭流
             } catch (Exception e2) {
                 log.error(e2.getMessage());
             }
         }
         return list;
         
     }
     
    /** 
     * @Title: isHasValues 
     * @Description: 判断一个对象所有属性是否有值，如果一个属性有值(分空)，则返回true
     * @param @param object
     * @param @return
     * @return boolean
     * @throws 
     */
     public boolean isHasValues(Object object){
         Field[] fields = object.getClass().getDeclaredFields();
         boolean flag = false;
         for (int i = 0; i < fields.length; i++) {
             String fieldName = fields[i].getName();
             String methodName = "get"+fieldName.substring(0, 1).toUpperCase()+fieldName.substring(1);
             Method getMethod;
             try {
                 getMethod = object.getClass().getMethod(methodName);
                 Object obj = getMethod.invoke(object);
                 if (null != obj && "".equals(obj)) {
                     flag = true;
                     break;
                 }
             } catch (Exception e) {
                 log.error(e.getMessage());
             }
             
         }
         return flag;
         
     }

}
